來幫昨天做好的骨架補上一些 CSS 樣式與動畫效果。
進一步組合 position: absolute
與 transform: translate(...)
的話,還可以得到 Drawer
元件唷 ヽ(́◕◞౪◟◕‵)ノ
將對話框背景設定為 position: fixed
並搭配 width: 100vw; height: 100vh;
達成滿版效果。而 display: flex;
則讓作為子元件的對話框本體可以在背景元件裡頭垂直水平置中。
const defaultBackdropStyle = css({
width: '100vw',
height: '100vh',
position: 'fixed',
inset: '0',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.6)',
animation: `${opacityIn} 0.25s`,
});
對話框本身的動畫效果拆成兩個部分:掛載時從透明逐漸顯現的效果由 opacityIn
負責,而卸載時則是先進行 unmountedAnimation
,結束後觸發 DialogBase
的 transitionend
事件,進而將整個對話框元件自畫面上卸載:
const opacityIn = keyframes`
from {
opacity: 0;
}
to {
opacity: 1;
}
`;
const defaultDialogStyle = css({
margin: '0',
padding: '24px',
borderRadius: '8px',
border: 'none',
backgroundColor: '#fff',
animation: `${opacityIn} 0.25s`,
});
const unmountedAnimation = css({
opacity: '0',
transition: 'opacity 0.25s',
});
透過 props.direction
控制對話框出現的位置,接著根據傳入的 direction
數值來決定對話框的 transform
效果要從哪一個方向開始。需注意 drawerUnmountedAnimation
也要配合 direction
來調整元件卸載前的移除動畫效果。
比如在 Drawer
的 props.direction = 'right'
時,預設 Drawer
滿版畫面高且靠右(right: 0
),並且 drawerUnmountedAnimation
要設定為 transform: translateX(50vw);
來讓 Drawer
消失時要往畫面右側退去,
const defaultDrawerStyle = useMemo(() => {
// 其他先略過
return css({
height: '100vh',
top: '0',
right: '0',
animation: `${slideInRight} 0.25s`,
});
}, [direction]);
const drawerUnmountedAnimation = useMemo(() => {
// 其他先略過
return css({
transform: 'translateX(50vw)',
transition: '0.25s ease',
});
}, [direction]);
對話框背景則是透過 opacityIn
與 backdropUnmountedAnimation
做出淡入淡出效果。
目前並未對 Dialog
與 Drawer
元件預設 min-width
等數值,有需要的話可以放在 Dialog
元件的 defaultDialogStyle
或 Drawer
元件的 defaultDrawerStyle
中。
比較花時間的地方是處理 props.direction
四個方位對應的 Drawer
動畫效果。邏輯倒是還好 (・∀・) 單純自用的話說不定連 props.direction
都可以不做,直接把樣式寫在 Drawer
裡面就搞定了。